﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DeviceServer
{
    /// <summary>
    /// 仪器仪表
    /// </summary>
    public class MeterSite:Site
    {
        private int tm;
        private Dictionary<string, Dictionary<string, string>> _questionDictionary;
        private List<string> _tm1quesion;
        private string _tm1Value;//题目1带测量的值
        private decimal _tm2DCValue;//题目2直流电压
        private decimal _tm2ACValue;//题目2交流电压
        private decimal _tm3Value;//题目3电流
        private decimal _tm4Value;//题目4交流电流
        public MeterSite()
        {
            InitQuestionData();
            
        }

        private void InitQuestionData()
        {

            _questionDictionary = new Dictionary<string, Dictionary<string, string>>();
            Dictionary<string, string> tm1 = new Dictionary<string, string>
            {
                {"R1", "(1,200]"},
                {"R2", "(20,2000]"},
                {"R3", "(200,20000]"},
                {"R4", "(2000,200000]"},
                {"R5", "(20000,+]"}
            };
            _questionDictionary.Add("tm1", tm1);

            Dictionary<string, string> tm2 = new Dictionary<string, string>
            {
                {"l5", "(-,0.25]"},
                {"U1", "(0.25,1]"},
                {"U2", "(1,2.5]"},
                {"U3", "(2.5,10]"},
                {"U4", "(10,50]"},
                {"U5", "(50,250]"},
                {"U6", "(250,500]"},
                {"U7", "(500,1000]"},
                {"u1", "(-,10]"},
                {"u2", "(10,50]"},
                {"u3", "(50,250]"},
                {"u4", "(250,500]"},
                {"u5", "(500,1000]"},
            };
            _questionDictionary.Add("tm2", tm2);

            Dictionary<String, string> tm3 = new Dictionary<string, string>()
            {
                {"I1", "(50,500]"},
                {"I2", "(5,50]"},
                {"I3", "(0.5,5]"},
                {"I4", "(0.005,0.5]"},
                {"I5", "(-,0.005]"},
            };
            _questionDictionary.Add("tm3", tm3);

            Dictionary<string, string> tm4 = new Dictionary<string, string>()
            {
                {"i1", "(-,5]"},
                {"i2", "(5,25]"},
                {"i3", "(25,50]"},
                {"i4", "(50,100]"},
                {"i5", "(100,250]"},
                {"i6", "(250,500]"},
            };
            _questionDictionary.Add("tm4", tm4);


            _tm1quesion = new List<string>()
            {
                "050","500","05k","50k","300","03k","30k"
            };
        }

        /// <summary>
        /// 获取试卷
        /// </summary>
        /// <returns></returns>
        public override string GetPaper()
        {
            Random random = new Random();
            var v = random.Next(4)+1;
            string cmd = $"paper:\"TM{v}\"";
            var bandState = "+paper:\"WYB band\"";//访问万用表、钳形表档位
            tm = v;
            switch (v)
            {
                case 1:
                    //电阻
                    var len = _tm1quesion.Count;
                    var index = random.Next(len);
                    _tm1Value = _tm1quesion[index];
                    var q = $"+paper:\"WYB:R {_tm1Value}\"";
                    cmd += q;                   

                    break;
                case 2:
                    //直流电压
                    var randDc = random.Next(1, 80) ;
                    if (randDc > 10 || randDc % 2 == 0)
                        randDc *= 10;//电压10的整数倍
                    _tm2DCValue = randDc;
                    var qDc = $"+paper:\"WYB:U {_tm2DCValue}\"";
                    cmd += qDc;
                    //交流电压
                    var randAc = random.Next(1, 80);
                    if (randAc > 10 || randAc % 2 == 0)
                        randAc *= 10;//电压10的整数倍
                    _tm2ACValue = randAc;
                    var qAc = $"+paper:\"WYB:u {_tm2ACValue}\"";
                    cmd += qAc;
                    break;
                case 3:
                    //测电流
                    var randCurrent = random.Next(1, 40);
                    if (randCurrent > 10 || randCurrent%2 == 0)
                        randCurrent *= 10;
                    _tm3Value = randCurrent;
                    var qCurrent = $"+paper:\"WYB:I {randCurrent}\"";
                    cmd += qCurrent;
                    break;
                case 4:
                    //测交流电流
                    var randac = random.Next(1, 40);
                    if (randac > 10 || randac % 2 == 0)
                        randac *= 10;
                    _tm4Value = randac;
                    var qac = $"+paper:\"QXB:i {randac}\"";
                    cmd += qac;
                    bandState = "+paper:\"QXB band\"";
                    break;
            }

            cmd += bandState;
            return cmd;
        }
 
        /// <summary>
        /// 解析答题步骤或内容
        /// </summary>
        /// <param name="content">答题内容</param>
        /// <param name="steps">答题步骤</param>
        public async override void Parse(string content, List<string> steps)
        {
            decimal score = 0;
            switch (tm)
            {
                case 1:
                    score = Parse1(steps);
                    break;
                case 2:
                    score = Parse2(steps);
                    break;
                case 3:
                    score = Parse3(steps);
                    break;
                case 4:
                    score = Parse4(steps);
                    break;

            }
            await Submit(score, "k1");
            //await UpDeviceState(DeviceState.free);
        }

       
        /// <summary>
        /// 主机端强制收卷
        /// </summary>
        public async override void Roll()
        {
            string cmd = "#END&";
            var senddata = Encoding.UTF8.GetBytes(cmd);
            await Session.SendAsync(senddata);
        }
        private decimal Parse1(List<string> steps)
        {
            //档位和AD_3 130 同时满足得分
            //校0    13-20
            string[] begin = new string[8];
            int firstIndex = 13;
            for (int i = 0; i < begin.Length; i++)
            {
                begin[i] ="WYB:AD_3 "+ firstIndex;
                firstIndex++;
            }
            //string[] begin = { "WYB:AD_3 12", "WYB:AD_3 13", "WYB:AD_3_14" };
            string[] progress = { "WYB:AD_3 129", "WYB:AD_3 130", "WYB:AD_3 131" };
            
            //ad
            var firstADstep = steps.FindLastIndex(i => i.Contains("AD_3") && begin.Contains(i));
            var lastADstep = steps.FindLastIndex(i => i.Contains("AD_3")&& progress.Contains(i));
            var turn0step = steps.FindLastIndex(i => i.Contains("AD_1"));

            //baud
            bool isbaudsuccess = false;
            List<string> bauds = GetBaud(_tm1Value, _questionDictionary["tm1"]);

            var lastBandu=  steps.LastOrDefault(i => i.Contains("WYB:band R"));
            if (!string.IsNullOrEmpty(lastBandu))
            {
               var baud=  lastBandu.Substring(lastBandu.Length - 2, 2);
                isbaudsuccess = bauds.Contains(baud);

            }
            int score = 0;
            if (isbaudsuccess)
            {
                if (firstADstep > -1 && turn0step > -1)
                    score += 10;
                if (lastADstep > -1)
                    score += 10;
            }

            return score;
        }
        private decimal Parse2(List<string> steps)
        {
             //根据返回的档位值判断档位正确后，返回AD_3 169（168 - 170之间）测量正确
             //1.判断ad值
            string[] adDcRange = { "WYB:AD_3 168", "WYB:AD_3 169", "WYB:AD_3 170" };
            string[] adAcRange = { "WYB:AD_3 193", "WYB:AD_3 194", "WYB:AD_3 195" };
            //var dcStep = steps.FindLastIndex(i => i.Contains("AD_3") && adDcRange.Contains(i));
            //var acStep = steps.FindLastIndex(i => i.Contains("AD_3") && adAcRange.Contains(i));
            var dcStep = steps.FindLastIndex(i =>  adDcRange.Contains(i));
            var acStep = steps.FindLastIndex(i =>  adAcRange.Contains(i));

            //2.判断档位
            //2.1直流电压
            bool isbaudDCsuccess = false;
            List<string> bauds = GetBaud(_tm2DCValue, _questionDictionary["tm2"]);
            var lastBandDCu = steps.LastOrDefault(i => i.Contains("WYB:band U"));
            if (!string.IsNullOrEmpty(lastBandDCu))
            {
                var baud = lastBandDCu.Substring(lastBandDCu.Length - 2, 2);
                isbaudDCsuccess = bauds.Contains(baud);
            }
            //2.2交流电压
            bool isbaudACsuccess = false;
            List<string> bauds2 = GetBaud(_tm2ACValue, _questionDictionary["tm2"]);
            var lastBandACu = steps.LastOrDefault(i => i.Contains("WYB:band u"));
            if (!string.IsNullOrEmpty(lastBandACu))
            {
                var baud = lastBandACu.Substring(lastBandACu.Length - 2, 2);
                isbaudACsuccess = bauds2.Contains(baud);
            }

            int score = 0;
            if (dcStep > -1 && isbaudDCsuccess)
                score += 10;
            if (acStep > -1 && isbaudACsuccess)
                score += 10;
            return score;
        }

        private decimal Parse3(List<string> steps)
        {
            //根据返回的档位值判断档位正确后，返回AD_3 207（206 - 208之间）测量正确
            //1.判断ad值
            string[] adRange = { "WYB:AD_3 206", "WYB:AD_3 207", "WYB:AD_3 208" };
            var lastADstep = steps.FindLastIndex(i => i.Contains("AD_3") && adRange.Contains(i));

            //2.判断档位 
            bool isbaudsuccess = false;
            List<string> bauds = GetBaud(_tm3Value, _questionDictionary["tm3"]);
            var lastBand= steps.LastOrDefault(i => i.Contains("WYB:band I"));
            if (!string.IsNullOrEmpty(lastBand))
            {
                var baud = lastBand.Substring(lastBand.Length - 2, 2);
                isbaudsuccess = bauds.Contains(baud);
            }

            int score = 0;
            if (lastADstep>-1)
                score += 10;
            if (isbaudsuccess)
                score += 10;
            return score;
        }

        private decimal Parse4(List<string> steps)
        {
            /**
              1.根据钳形表返回的档位值判断档位正确后，
                    钳形表返回band CHK1表示钳形表钳口打开，然后返回band CHK0钳形表钳口闭合，
                    如果此时基础板返回D0则此时钳形表已放到正确位置测量正确。
            2.基础板返回N0表示验电笔放到N触点（火线）测电正确，基础板返回L0表示验电笔放到L触点（零线）测电错误。


            */

            //判断档位
            bool isbaudsuccess = false;
            List<string> bauds = GetBaud(_tm4Value, _questionDictionary["tm4"]);
            var lastBand = steps.LastOrDefault(i => i.Contains("QXB:band i"));
            if (!string.IsNullOrEmpty(lastBand))
            {
                var baud = lastBand.Substring(lastBand.Length - 2, 2);
                isbaudsuccess = bauds.Contains(baud);              
            }

            //钳形表动作 开->关
            var openIndex = steps.FindLastIndex(i => i.Contains("QXB:band CHK1"));
            var closeIndex = steps.FindLastIndex(i => i.Contains("QXB:band CHK0"));
            var d0Index = steps.FindLastIndex(i => i.Contains("JCB:D0"));
            var n0Index = steps.FindLastIndex(i => i.Contains("JCB:N0"));
            var l0Index = steps.FindLastIndex(i => i.Contains("JCB:L0"));

            //算分
            int score = 0;
            if (isbaudsuccess)
                score += 5;
            if (openIndex>-1&& closeIndex > openIndex)
                score += 5;
            if (closeIndex>-1&& d0Index > closeIndex)
                score += 5;

            //N0正确，L0错误， 先L0后N0也可以?
            if (n0Index > -1 && l0Index > -1)
            {
                if (n0Index > l0Index)
                {
                    score += 5;
                }
            }
            if(n0Index>-1 && l0Index==-1)
                score += 5;

            return score;
        }

        private List<string> GetBaud(string value,Dictionary<string,string> dictionary )
        {
            if (value.Contains("k"))
                value = value.Replace('k', '0')+00;
            decimal v;
            decimal.TryParse(value, out v);
            
            return GetBaud(v,dictionary);
        }
        private List<string> GetBaud(decimal value, Dictionary<string, string> dictionary)
        {
            //return dictionary.Values.Where(key => IsInRange(value, dictionary[key])).ToList();

            List<string> bands = new List<string>();
            foreach (var key in dictionary.Keys)
            {
                if(IsInRange(value, dictionary[key]))
                    bands.Add(key);
            }
            return bands;
        }

        private bool IsInRange(decimal value, string range)
        {
            int index = range.IndexOf(",", StringComparison.Ordinal);
            string v1 = range.Substring(1, index - 1);
            string v2 = range.Substring(index + 1, range.Length - (index + 1) - 1);
            decimal left;
            decimal right;
            var leftsuccess = decimal.TryParse(v1, out left);
            var rightsuccess = decimal.TryParse(v2, out right);
            if (leftsuccess && rightsuccess)
            {
                return value > left && value <= right;
            }
            if (!leftsuccess)
            {
                return value <= right;
            }
            if (!rightsuccess)
            {
                return value > left;
            }
            return false;
        }

        
    }
}

